﻿package lib 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import flash.utils.clearInterval;
	import flash.utils.setInterval;
	/**
	 * ...
	 * @author kabuto.boy
	 */
	public class SoundLoader extends EventDispatcher
	{
		private var _source:String;
		private var _request:URLRequest;
		
		private var _bytesLoaded:int;
		private var _bytesTotal:int;
		
		private var _sound:Sound;
		private var _channel:SoundChannel;
		
		private var _delay:int = 100;
		private var _time:Number = 0;
		private var _length:Number = 0;
		private var _interval:int = 0;
		
		private var _volume:Number = 1;
		
		public var playing:Boolean = false;
		public var soundCompleted:Boolean = false;
		
		public function SoundLoader() 
		{
			//load($source);
		}
		
		public function load($source:String):void
		{
			_source = $source;
			_request = new URLRequest(_source);
			_sound = new Sound(_request);
			
			_sound.addEventListener(Event.COMPLETE, onEvent);
			_sound.addEventListener(IOErrorEvent.IO_ERROR, onEvent);
			_sound.addEventListener(ProgressEvent.PROGRESS, onEvent);
		}
		
		private function onEvent(event:*):void
		{
			switch(event.type) {
				case "complete" :
					_sound.removeEventListener(Event.COMPLETE, onEvent);
					_sound.removeEventListener(IOErrorEvent.IO_ERROR, onEvent);
					_sound.removeEventListener(ProgressEvent.PROGRESS, onEvent);
					
					var eComplete:Event = new Event(Event.COMPLETE);
					dispatchEvent(eComplete);
					
					break;
				case "ioError" :
					_sound.removeEventListener(Event.COMPLETE, onEvent);
					_sound.removeEventListener(IOErrorEvent.IO_ERROR, onEvent);
					_sound.removeEventListener(ProgressEvent.PROGRESS, onEvent);
					
					var eIOError:IOErrorEvent = new IOErrorEvent(IOErrorEvent.IO_ERROR);
					dispatchEvent(eIOError);
					
					break;
				case "progress" :
					_bytesLoaded = _sound.bytesLoaded;
					_bytesTotal = _sound.bytesTotal;
					
					var eProgress:ProgressEvent = new ProgressEvent(ProgressEvent.PROGRESS);
					dispatchEvent(eProgress);
					
					break;
				case "soundComplete" :
					_channel.removeEventListener(Event.SOUND_COMPLETE, onEvent);
					
					stop();
					
					soundCompleted = true;
					
					var eSoundComplete:Event = new Event(Event.SOUND_COMPLETE);
					dispatchEvent(eSoundComplete);
					
					break;
			}
		}
		
		private function _check():void
		{
			_time = _channel.position;
			
			var _event:Event = new Event("check");
			dispatchEvent(_event);
		}
		
		public function play(time:Number = 0):void
		{
			if(_channel) _channel.stop();
			_channel = _sound.play(time);
			_time = time;
			_length = _sound.length;
			this.volume = _volume;
			
			soundCompleted = false;
			playing = true;
			
			if (!_channel.hasEventListener(Event.SOUND_COMPLETE))
				_channel.addEventListener(Event.SOUND_COMPLETE, onEvent);
			
			if (!_interval)
				_interval = setInterval(_check, _delay);
		}
		
		public function resume():void
		{
			_channel = _sound.play(_time);
			
			if (!_channel.hasEventListener(Event.SOUND_COMPLETE))
				_channel.addEventListener(Event.SOUND_COMPLETE, onEvent);
				
			if (!_interval)
				_interval = setInterval(_check, _delay);
		}
		
		public function _play(position:Number = NaN):void
		{
			play(position * _length);
		}
		
		public function pause():void
		{
			_time = _channel.position;
			
			playing = false;
			
			_channel.stop();
			clearInterval(_interval);
			_interval = 0;
		}
		
		public function stop():void
		{
			_time = 0;
			
			playing = false;
			
			_channel.stop();
			clearInterval(_interval);
			_interval = 0;
		}
		
		public function set volume(value:Number):void
		{
			try { 
				_volume = value;
				var _soundTransform:SoundTransform = _channel.soundTransform;
				_soundTransform.volume = value;
				_channel.soundTransform = _soundTransform; 
			} catch (error:*) { }
		}
		
		public function get volume() { return _volume; }
		public function get sound():Sound { return _sound; }
		public function get channel():SoundChannel { return _channel; }
		public function get position():Number { return _time / _length; }
		public function get loaded():Number { return _bytesLoaded / _bytesTotal; }
		
	}

}